﻿//===================================================================================
// Copyright (c) Ryan Garrett.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===================================================================================

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using Caffeine.Core.Test.TestModel;
using Caffeine.Core.Test.TestModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Caffeine.Core.Test
{
    [TestClass]
    public class ModelFieldTester
    {
        [TestMethod]
        public void TestWrappedProperties()
        {
            IModelFactory factory = new ModelFactory();
            ModelForAutoRegisterPropertyTesting viewModel = factory.CreateModel<ModelForAutoRegisterPropertyTesting>();

            List<String> viewModelChanges = new List<String>();
            List<String> propertyChanges = new List<String>();

            viewModel.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                viewModelChanges.Add(e.PropertyName);
            };

            viewModel.EnumProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.NullableEnumForTesting.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.StringProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.ObjectProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.Int32Property.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.NullableCharProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.ChildProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.ChildrenProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.EnumWrappedProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.NullableEnumWrappedProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.StringWrappedProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.ObjectWrappedProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.Int32WrappedProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.NullableCharWrappedProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.ChildWrappedProperty.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.ChildrenWrapped.PropertyChanged += delegate(Object sender, PropertyChangedEventArgs e)
            {
                propertyChanges.Add(e.PropertyName);
            };

            viewModel.EnumProperty.Value = EnumForTesting.TestValue2;
            Assert.AreEqual(viewModelChanges.Count, 4);
            Assert.AreEqual(viewModelChanges[0], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[1], "IsDirty");
            Assert.AreEqual(viewModelChanges[2], "InvalidPropertyCount");
            Assert.AreEqual(viewModelChanges[3], "IsInvalid");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.NullableEnumForTesting.Value = EnumForTesting.TestValue2;
            Assert.AreEqual(viewModelChanges.Count, 2);
            Assert.AreEqual(viewModelChanges[0], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[1], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.StringProperty.Value = "SomeValue";
            Assert.AreEqual(viewModelChanges.Count, 2);
            Assert.AreEqual(viewModelChanges[0], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[1], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ObjectProperty.Value = new Object();
            Assert.AreEqual(viewModelChanges.Count, 2);
            Assert.AreEqual(viewModelChanges[0], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[1], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.Int32Property.Value = 3;
            Assert.AreEqual(viewModelChanges.Count, 2);
            Assert.AreEqual(viewModelChanges[0], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[1], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.NullableCharProperty.Value = 'C';
            Assert.AreEqual(viewModelChanges.Count, 2);
            Assert.AreEqual(viewModelChanges[0], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[1], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ChildProperty.Value = factory.CreateModel<ModelForAutoRegisterPropertyTesting>();
            Assert.AreEqual(viewModelChanges.Count, 2);
            Assert.AreEqual(viewModelChanges[0], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[1], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ChildrenProperty.Add(factory.CreateModel<ModelForAutoRegisterPropertyTesting>());
            Assert.AreEqual(viewModelChanges.Count, 2);
            Assert.AreEqual(viewModelChanges[0], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[1], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 7);
            Assert.AreEqual(propertyChanges[0], "Count");
            Assert.AreEqual(propertyChanges[1], "AddedModelCount");
            Assert.AreEqual(propertyChanges[2], "AddedModels");
            Assert.AreEqual(propertyChanges[3], "ContainsAddedModels");
            Assert.AreEqual(propertyChanges[4], "IsDirty");
            Assert.AreEqual(propertyChanges[5], "ValidationErrors");
            Assert.AreEqual(propertyChanges[6], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.EnumWrapped = EnumForTesting.TestValue4;
            Assert.AreEqual(viewModelChanges.Count, 7);
            Assert.AreEqual(viewModelChanges[0], "EnumWrapped");
            Assert.AreEqual(viewModelChanges[1], "EnumWrappedIsDefault");
            Assert.AreEqual(viewModelChanges[2], "EnumWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[3], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[4], "EnumWrappedValidationErrors");
            Assert.AreEqual(viewModelChanges[5], "EnumWrappedIsInvalid");
            Assert.AreEqual(viewModelChanges[6], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.NullableEnumWrapped = EnumForTesting.TestValue5;
            Assert.AreEqual(viewModelChanges.Count, 7);
            Assert.AreEqual(viewModelChanges[0], "NullableEnumWrapped");
            Assert.AreEqual(viewModelChanges[1], "NullableEnumWrappedIsDefault");
            Assert.AreEqual(viewModelChanges[2], "NullableEnumWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[3], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[4], "NullableEnumWrappedValidationErrors");
            Assert.AreEqual(viewModelChanges[5], "NullableEnumWrappedIsInvalid");
            Assert.AreEqual(viewModelChanges[6], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.StringWrapped = "SomeValue";
            Assert.AreEqual(viewModelChanges.Count, 7);
            Assert.AreEqual(viewModelChanges[0], "StringWrapped");
            Assert.AreEqual(viewModelChanges[1], "StringWrappedIsDefault");
            Assert.AreEqual(viewModelChanges[2], "StringWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[3], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[4], "StringWrappedValidationErrors");
            Assert.AreEqual(viewModelChanges[5], "StringWrappedIsInvalid");
            Assert.AreEqual(viewModelChanges[6], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ObjectWrapped = new Object();
            Assert.AreEqual(viewModelChanges.Count, 7);
            Assert.AreEqual(viewModelChanges[0], "ObjectWrapped");
            Assert.AreEqual(viewModelChanges[1], "ObjectWrappedIsDefault");
            Assert.AreEqual(viewModelChanges[2], "ObjectWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[3], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[4], "ObjectWrappedValidationErrors");
            Assert.AreEqual(viewModelChanges[5], "ObjectWrappedIsInvalid");
            Assert.AreEqual(viewModelChanges[6], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.Int32Wrapped = 5;
            Assert.AreEqual(viewModelChanges.Count, 7);
            Assert.AreEqual(viewModelChanges[0], "Int32Wrapped");
            Assert.AreEqual(viewModelChanges[1], "Int32WrappedIsDefault");
            Assert.AreEqual(viewModelChanges[2], "Int32WrappedIsDirty");
            Assert.AreEqual(viewModelChanges[3], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[4], "Int32WrappedValidationErrors");
            Assert.AreEqual(viewModelChanges[5], "Int32WrappedIsInvalid");
            Assert.AreEqual(viewModelChanges[6], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.NullableCharWrapped = 'V';
            Assert.AreEqual(viewModelChanges.Count, 7);
            Assert.AreEqual(viewModelChanges[0], "NullableCharWrapped");
            Assert.AreEqual(viewModelChanges[1], "NullableCharWrappedIsDefault");
            Assert.AreEqual(viewModelChanges[2], "NullableCharWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[3], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[4], "NullableCharWrappedValidationErrors");
            Assert.AreEqual(viewModelChanges[5], "NullableCharWrappedIsInvalid");
            Assert.AreEqual(viewModelChanges[6], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ChildWrapped = factory.CreateModel<ModelForAutoRegisterPropertyTesting>();
            Assert.AreEqual(viewModelChanges.Count, 7);
            Assert.AreEqual(viewModelChanges[0], "ChildWrapped");
            Assert.AreEqual(viewModelChanges[1], "ChildWrappedIsDefault");
            Assert.AreEqual(viewModelChanges[2], "ChildWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[3], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[4], "ChildWrappedValidationErrors");
            Assert.AreEqual(viewModelChanges[5], "ChildWrappedIsInvalid");
            Assert.AreEqual(viewModelChanges[6], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 5);
            Assert.AreEqual(propertyChanges[0], "Value");
            Assert.AreEqual(propertyChanges[1], "IsDefault");
            Assert.AreEqual(propertyChanges[2], "IsDirty");
            Assert.AreEqual(propertyChanges[3], "ValidationErrors");
            Assert.AreEqual(propertyChanges[4], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ChildrenWrapped.Add(factory.CreateModel<ModelForAutoRegisterPropertyTesting>());
            Assert.AreEqual(viewModelChanges.Count, 5);
            Assert.AreEqual(viewModelChanges[0], "ChildrenWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[1], "DirtyPropertyCount");
            Assert.AreEqual(viewModelChanges[2], "ChildrenWrappedValidationErrors");
            Assert.AreEqual(viewModelChanges[3], "ChildrenWrappedIsInvalid");
            Assert.AreEqual(viewModelChanges[4], "InvalidPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 7);
            Assert.AreEqual(propertyChanges[0], "Count");
            Assert.AreEqual(propertyChanges[1], "AddedModelCount");
            Assert.AreEqual(propertyChanges[2], "AddedModels");
            Assert.AreEqual(propertyChanges[3], "ContainsAddedModels");
            Assert.AreEqual(propertyChanges[4], "IsDirty");
            Assert.AreEqual(propertyChanges[5], "ValidationErrors");
            Assert.AreEqual(propertyChanges[6], "IsInvalid");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.NullableEnumWrappedProperty.Commit();
            Assert.AreEqual(viewModelChanges.Count, 3);
            Assert.AreEqual(viewModelChanges[0], "NullableEnumWrappedCommittedValue");
            Assert.AreEqual(viewModelChanges[1], "NullableEnumWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[2], "DirtyPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 2);
            Assert.AreEqual(propertyChanges[0], "CommittedValue");
            Assert.AreEqual(propertyChanges[1], "IsDirty");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.StringWrappedProperty.Commit();
            Assert.AreEqual(viewModelChanges.Count, 3);
            Assert.AreEqual(viewModelChanges[0], "StringWrappedCommittedValue");
            Assert.AreEqual(viewModelChanges[1], "StringWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[2], "DirtyPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 2);
            Assert.AreEqual(propertyChanges[0], "CommittedValue");
            Assert.AreEqual(propertyChanges[1], "IsDirty");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ObjectWrappedProperty.Commit();
            Assert.AreEqual(viewModelChanges.Count, 3);
            Assert.AreEqual(viewModelChanges[0], "ObjectWrappedCommittedValue");
            Assert.AreEqual(viewModelChanges[1], "ObjectWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[2], "DirtyPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 2);
            Assert.AreEqual(propertyChanges[0], "CommittedValue");
            Assert.AreEqual(propertyChanges[1], "IsDirty");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.Int32WrappedProperty.Commit();
            Assert.AreEqual(viewModelChanges.Count, 3);
            Assert.AreEqual(viewModelChanges[0], "Int32WrappedCommittedValue");
            Assert.AreEqual(viewModelChanges[1], "Int32WrappedIsDirty");
            Assert.AreEqual(viewModelChanges[2], "DirtyPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 2);
            Assert.AreEqual(propertyChanges[0], "CommittedValue");
            Assert.AreEqual(propertyChanges[1], "IsDirty");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.NullableCharWrappedProperty.Commit();
            Assert.AreEqual(viewModelChanges.Count, 3);
            Assert.AreEqual(viewModelChanges[0], "NullableCharWrappedCommittedValue");
            Assert.AreEqual(viewModelChanges[1], "NullableCharWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[2], "DirtyPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 2);
            Assert.AreEqual(propertyChanges[0], "CommittedValue");
            Assert.AreEqual(propertyChanges[1], "IsDirty");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ChildWrappedProperty.Commit();
            Assert.AreEqual(viewModelChanges.Count, 3);
            Assert.AreEqual(viewModelChanges[0], "ChildWrappedCommittedValue");
            Assert.AreEqual(viewModelChanges[1], "ChildWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[2], "DirtyPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 2);
            Assert.AreEqual(propertyChanges[0], "CommittedValue");
            Assert.AreEqual(propertyChanges[1], "IsDirty");
            viewModelChanges.Clear();
            propertyChanges.Clear();

            viewModel.ChildrenWrapped.Commit();
            Assert.AreEqual(viewModelChanges.Count, 2);
            Assert.AreEqual(viewModelChanges[0], "ChildrenWrappedIsDirty");
            Assert.AreEqual(viewModelChanges[1], "DirtyPropertyCount");
            Assert.AreEqual(propertyChanges.Count, 7);
            Assert.AreEqual(propertyChanges[0], "CommittedModelCount");
            Assert.AreEqual(propertyChanges[1], "CommittedModels");
            Assert.AreEqual(propertyChanges[2], "ContainsCommittedModels");
            Assert.AreEqual(propertyChanges[3], "AddedModelCount");
            Assert.AreEqual(propertyChanges[4], "AddedModels");
            Assert.AreEqual(propertyChanges[5], "ContainsAddedModels");
            Assert.AreEqual(propertyChanges[6], "IsDirty");
        }

        [TestMethod]
        public void SimpleAdornedFieldTest()
        {
            IModelFactory factory = new ModelFactory();
            ModelForFieldTestingA viewModel = factory.CreateModel<ModelForFieldTestingA>();
            viewModel.ChildA.Value = factory.CreateModel<ModelForFieldTestingB>();
            (viewModel.ChildA.Value as ModelForFieldTestingB).CollectionA.Add(factory.CreateModel<ModelForFieldTestingA>());
            (viewModel.ChildA.Value as ModelForFieldTestingB).CollectionB.Add(factory.CreateModel<ModelForFieldTestingC>());
            (viewModel.ChildA.Value as ModelForFieldTestingB).StringPropertyA.Value = "SomeValue";
            (viewModel.ChildA.Value as ModelForFieldTestingB).ChildA.Value = factory.CreateModel<ModelForFieldTestingC>();

            viewModel.StringPropertyA.Value = "SomeValue";
            ModelForFieldTestingC viewModelC = factory.CreateModel<ModelForFieldTestingC>();
            viewModelC.StringPropertyA.Value = "SomeValue";
            viewModelC.StringPropertyB.Value = "SomeValue";
            viewModelC.StringPropertyC.Value = "SomeValue";
            viewModelC.ChildA.Value = factory.CreateModel<ModelForFieldTestingA>();
            viewModelC.ChildB.Value = factory.CreateModel<ModelForFieldTestingB>();
            viewModelC.ChildC.Value = factory.CreateModel<ModelForFieldTestingC>();
            viewModelC.ChildA.Value.CollectionA.Add(factory.CreateModel<ModelForFieldTestingA>());
            viewModelC.ChildB.Value.CollectionB.Add(factory.CreateModel<ModelForFieldTestingB>());
            viewModelC.ChildB.Value.CollectionA.Add(factory.CreateModel<ModelForFieldTestingA>());
            viewModelC.ChildC.Value.CollectionC.Add(factory.CreateModel<ModelForFieldTestingC>());
            viewModelC.ChildC.Value.CollectionB.Add(factory.CreateModel<ModelForFieldTestingC>());
            viewModelC.ChildC.Value.CollectionC.Add(factory.CreateModel<ModelForFieldTestingC>());
        }

        [TestMethod]
        [ExpectedException(typeof(TargetInvocationException))]
        public void PropertyValueTypeMistmatch()
        {
            IModelFactory factory = new ModelFactory();
            ModelForPropertyValueTypeMistmatch viewModel = factory.CreateModel<ModelForPropertyValueTypeMistmatch>();
        }

        [TestMethod]
        [ExpectedException(typeof(TargetInvocationException))]
        public void CollectionValueTypeMismatch()
        {
            IModelFactory factory = new ModelFactory();
            ModelForCollectionValueTypeMismatch viewModel = factory.CreateModel<ModelForCollectionValueTypeMismatch>();
        }

        [TestMethod]
        [ExpectedException(typeof(TargetInvocationException))]
        public void PropertyRegisteredAsCollection()
        {
            IModelFactory factory = new ModelFactory();
            ModelForPropertyRegisteredAsCollection viewModel = factory.CreateModel<ModelForPropertyRegisteredAsCollection>();
        }

        [TestMethod]
        [ExpectedException(typeof(TargetInvocationException))]
        public void CollectionRegisteredAsProperty()
        {
            IModelFactory factory = new ModelFactory();
            ModelForCollectionRegisteredAsProperty viewModel = factory.CreateModel<ModelForCollectionRegisteredAsProperty>();
        }

        [TestMethod]
        [ExpectedException(typeof(TargetInvocationException))]
        public void RegisterNonModelProperty()
        {
            IModelFactory factory = new ModelFactory();
            ModelForRegisterNonModelProperty viewModel = factory.CreateModel<ModelForRegisterNonModelProperty>();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void RegisterWrongName()
        {
            IModelFactory factory = new ModelFactory();
            ModelForRegisterWrongName viewModel = factory.CreateModel<ModelForRegisterWrongName>();
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void ShadowedFieldsTest()
        {
            IModelFactory factory = new ModelFactory();
            ModelForShadowedFieldsTestB viewModel = factory.CreateModel<ModelForShadowedFieldsTestB>();
        }
    }
}
